<h2>Why is this an issue?</h2>
<p>To prevent potential <a href="https://en.wikipedia.org/wiki/Deadlock">deadlocks</a> in an application, it is crucial to release any locks that are
acquired within a method along all possible execution paths.</p>
<p>Failing to release locks properly can lead to potential deadlocks, where the lock might not be released, causing issues in the application.</p>
<p>This rule specifically focuses on tracking the following types from the <code>System.Threading</code> namespace:</p>
<ul>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.monitor"><code>Monitor</code></a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.mutex"><code>Mutex</code></a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlock"><code>ReaderWriterLock</code></a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim"><code>ReaderWriterLockSlim</code></a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock"><code>SpinLock</code> </a> </li>
</ul>
<p>An issue is reported when a lock is acquired within a method but not released on all paths.</p>
<h3>Exceptions</h3>
<p>If the lock is never released within the method, no issue is raised, assuming that the callers will handle the release.</p>
<h2>How to fix it</h2>
<p>To make sure that a lock is always released correctly, you can follow one of these two methods:</p>
<ul>
  <li> Use a <a
  href="https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/synclock-statement"><code>SyncLock</code></a> statement
  with your lock object. </li>
  <li> Use a <a
  href="https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/try-catch-finally-statement"><code>Try-Finally</code></a>
  statement and put the release of your lock object within a <a
  href="https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/try-catch-finally-statement#finally-block"><code>Finally</code></a> block. </li>
</ul>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
Class Example
    Private obj As Object = New Object()

    Public Sub DoSomethingWithMonitor()
        Monitor.Enter(obj) ' Noncompliant: not all paths release the lock

        If IsInitialized() Then
            ' ...
            Monitor.Exit(obj)
        End If
    End Sub
End Class
</pre>
<pre data-diff-id="2" data-diff-type="noncompliant">
Class Example
    Private lockObj As ReaderWriterLockSlim = New ReaderWriterLockSlim()

    Public Sub DoSomethingWithReaderWriteLockSlim()
        lockObj.EnterReadLock() ' Noncompliant: not all paths release the lock
        If IsInitialized() Then
            ' ...
            lockObj.ExitReadLock()
        End If
    End Sub
End Class
</pre>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
Class Example
    Private obj As Object = New Object()

    Public Sub DoSomethingWithMonitor()
        SyncLock obj ' Compliant: the lock will be released at the end of the SyncLock block
            If IsInitialized() Then
                ' ...
            End If
        End SyncLock
    End Sub
End Class
</pre>
<pre data-diff-id="2" data-diff-type="compliant">
Class Example
    Private lockObj As ReaderWriterLockSlim = New ReaderWriterLockSlim()

    Public Sub DoSomethingWithReaderWriteLockSlim()
        lockObj.EnterReadLock() ' Compliant: the lock will be released in the finally block

        Try
            If IsInitialized() Then
                ' ...
            End If
        Finally
            lockObj.ExitReadLock()
        End Try
    End Sub
End Class
</pre>
<h2>Resources</h2>
<ul>
  <li> <a
  href="https://docs.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives#synchronization-of-access-to-a-shared-resource">Synchronization of access to a shared resource</a> </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/459">CWE-459 - Incomplete Cleanup</a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/synclock-statement"><code>SyncLock</code>
  statement</a> </li>
  <li> <a
  href="https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/try-catch-finally-statement#finally-block"><code>Finally</code> block</a> </li>
</ul>

